

#include <stdlib.h>
#include <assert.h>
#include "asmtype.h"
#include "character.h"
#include "input.h"
#include "findstr.h"
#include "lexical.h"






/* 定义字符类别, 这个作为状态机矩阵对横坐标. */
#define   LEX_CH_DOT      (0)     /* .            */
#define   LEX_CH_DOLLAR   (1)     /* $            */
#define   LEX_CH_UNDLINE  (2)     /* _            */
#define   LEX_CH_LOWCASE  (3)     /* a-z          */
#define   LEX_CH_UPRCASE  (4)     /* A-Z          */
#define   LEX_CH_ZERO     (5)     /* 0            */
#define   LEX_CH_NOZERO   (6)     /* 1-9          */
#define   LEX_CH_SIGN     (7)     /* +-           */
#define   LEX_CH_ALPHA    (8)     /* @            */
#define   LEX_CH_QUOTA    (9)    /* "            */
#define   LEX_CH_BSLASH   (10)    /* \            */
#define   LEX_CH_COLON    (11)    /* :            */
#define   LEX_CH_COMMA    (12)    /* ,            */
#define   LEX_CH_SPACE    (13)    /* 0x20         */
#define   LEX_CH_LINED    (14)    /* \n           */
#define   LEX_CH_OTHER    (15)    /* other        */
#define   LEX_CH_FILED    (16)


/* 内部使用的终结状态. */
#define   LEX_I_NOTEND    (0)     /* 中间的未决的状态.            */
#define   LEX_I_COMMAND   (1)     /* .section, .align, .tetra ... */
#define   LEX_I_GREG      (2)     /* $12, $0, ...                 */
#define   LEX_I_ALPHA     (3)     /* @, @+1, @-2,  ...            */
#define   LEX_I_LABLE     (4)     /* lable, instruct, sreg, const */
#define   LEX_I_ZERO      (5)     /* 0                            */
#define   LEX_I_HEX       (6)     /* 0x1fe, 0x2345, 0x4ead, ...   */
#define   LEX_I_SZERO     (7)     /* +0, -0                       */
#define   LEX_I_SINT      (8)     /* +123, 1200, -234, -809, ...  */
#define   LEX_I_FLOAT     (9)     /* 0.256, -2.34, +4.56, ...     */
#define   LEX_I_FLOATEe   (10)    /* +2.34e-34, -3.4E12, ...      */
#define   LEX_I_STRING    (11)    /* "ABce", "字符串", ...        */
#define   LEX_I_COLON     (12)    /* :                            */
#define   LEX_I_COMMA     (13)    /* ,                            */
#define   LEX_I_LINED     (14)    /* \n                           */
#define   LEX_I_FILED     (15)    /* \n                           */
#define   LEX_I_ERROR     (16)    /* 错误....                     */


/* 
 * 当 next_token 返回 type == LEX_I_ERROR 时。
 * info 中的信息就是下面宏定义的值..
 * 用来细分错误原因.
 */
#define   ERR_INF_STATE1    (1)       /* 程序错误, 状态超过最大值.. */
#define   ERR_INF_STATE2    (2)       /* 程序错误, 状态中的 st 错误.. */
#define   ERR_INF_STATE3    (3)       /* 程序错误, 状态中的 fun 值错误.. */
#define   ERR_INF_STATE4    (4)       /* 程序错误, type 错误.. */

#define   ERR_INF_MAXLEN    (5)       /* 字串太长了，不能处理..     */
#define   ERR_INF_FUN1      (6)       /* 0 后面是字母，但不是 xX    */
#define   ERR_INF_FUN2      (7)       /* 0x 后面是字母，但不是 a-f  */
#define   ERR_INF_FUN3      (8)       /* 0.09 后面是字母，但不是 eE */
#define   ERR_INF_PUDO      (9)       /* .xxx 不是个伪命令 */
#define   ERR_INF_GREG1     (10)      /* $ 后面超过了 3 个数字 */
#define   ERR_INF_GREG2     (11)      /* $ 后面解析数字失败 */
#define   ERR_INF_GREG3     (12)      /* $ 后面超过了 255  */

#define   ERR_INF_ALPH1     (13)      /* @ 后面只有一个字符，程序检查错误 */
#define   ERR_INF_ALPH2     (14)      /* @ 数字解析错误 */
#define   ERR_INF_ALPH3     (15)      /* @ 后面不是正负号, 程序检查错误 */

#define   ERR_INF_HEX1      (16)      /* hex 中只有 0x 没有其他 */
#define   ERR_INF_HEX2      (17)      /* hex 中解析数字失败.. */

#define   ERR_INF_SZER1     (18)      /* SZERO 中 没有数字部分. */
#define   ERR_INF_SZER2     (19)      /* SZERO 中 没有正负号. */


#define   ERR_INF_SINT1     (20)      /* SINT 中没有字符串 */
#define   ERR_INF_SINT2     (21)      /* SINT 中翻译字符串错误 */
#define   ERR_INF_SINT3     (22)      /* SINT 中翻译字符串错误 */
#define   ERR_INF_SINT4     (23)      /* SINT 中负数太大不能表示 */
#define   ERR_INF_SINT5     (24)      /* SINT 中翻译字符串错误 */

#define   ERR_INF_FLOAT     (25)      /* FLOAT 中翻译字符串错误 */
#define   ERR_INF_FLTE      (26)      /* FLOATeE 中翻译字符串错误 */

#define   ERR_INF_DEFLT     (27)      /* 走到 default 流程中了 */








/*
 * 状态机定义，行:当前状态，列:下一个字符的类别。
 * 每次获得的 action 由三部分组成澹:
 *     store() function? value?
 */
#define   _PASS_     (0)
#define   _STORE_    (1)
#define   _UNPUT_    (2)

#define   _ERR_      (0)
#define   _END_      (1)
#define   _OK_       (2)
#define   _FUN1_      (3)
#define   _FUN2_      (4)
#define   _FUN3_      (5)

#define   PO(s)      ( s | (_PASS_)<<16 | (_OK_)<<24 )
#define   SO(s)      ( s | (_STORE_)<<16 | (_OK_)<<24 )
#define   PE(s)      ( s | (_PASS_)<<16 | (_END_)<<24 )
#define   UE(s)      ( s | (_UNPUT_)<<16 | (_END_)<<24 )
#define   UR(s)      ( s | (_UNPUT_)<<16 | (_ERR_)<<24 )
#define   SF1(s)     ( s | (_STORE_)<<16 | (_FUN1_)<<24 )
#define   SF2(s)     ( s | (_STORE_)<<16 | (_FUN2_)<<24 )
#define   SF3(s)     ( s | (_STORE_)<<16 | (_FUN3_)<<24 )

#define  MAX_STATE      25 
static  tetra  state_machine[MAX_STATE][16] = {
/*  0 */   { PO(1),   PO(3),  SO(6),   SO(6),   SO(6), SO(11), SO(16),  SO(14), PO(8), PO(22),      0, PE(12), PE(13),  PO(0), PE(14),    0   },
/*  1 */   {     0,       0,      0,   SO(2),       0,      0,      0,      0,      0,      0,      0,      0,      0,      0,  UR(0),    0   },
/*  2 */   {     0,       0,      0,   SO(2),       0,      0,      0,      0,      0,      0,      0,      0,      0,  PE(1),  UE(1),    0   },
/*  3 */   {     0,       0,      0,       0,       0,  SO(4),  SO(5),      0,      0,      0,      0,      0,      0,      0,  UR(0),    0   },
/*  4 */   {     0,       0,      0,       0,       0,      0,      0,      0,      0,      0,      0,      0,  UE(2),  PE(2),  UE(2),    0   },
/*  5 */   {     0,       0,      0,       0,       0,  SO(5),  SO(5),      0,      0,      0,      0,      0,  UE(2),  PE(2),  UE(2),    0   },
/*  6 */   {     0,       0,  SO(6),   SO(6),   SO(6),  SO(6),  SO(6),      0,      0,      0,      0,  UE(4),  UE(4),  PE(4),  UE(4),    0   },
/*  7 */   {     0,       0,      0,       0,       0,      0,      0,      0,      0,      0,      0,      0,  UE(3),  PE(3),  UE(3),    0   },
/*  8 */   {     0,       0,      0,       0,       0,      0,      0,  SO(9),      0,      0,      0,      0,  UE(3),  PO(8),  UE(3),    0   },
/*  9 */   {     0,       0,      0,       0,       0,  SO(7), SO(10),      0,      0,      0,      0,      0,      0,  PO(9),  UR(0),    0   },
/* 10 */   {     0,       0,      0,       0,       0, SO(10), SO(10),      0,      0,      0,      0,      0,  UE(3),  PE(3),  UE(3),    0   },
/* 11 */   { SO(17),      0,      0, SF1(12), SF1(12),      0,      0,      0,      0,      0,      0,      0,  UE(5),  PE(5),  UE(5),    0   },
/* 12 */   {     0,       0,      0, SF2(13), SF2(13), SO(13), SO(13),      0,      0,      0,      0,      0,      0,      0,  UR(0),    0   },
/* 13 */   {     0,       0,      0, SF2(13), SF2(13), SO(13), SO(13),      0,      0,      0,      0,      0,  UE(6),  PE(6),  UE(6),    0   },
/* 14 */   {     0,       0,      0,       0,       0, SO(15), SO(16),      0,      0,      0,      0,      0,      0,      0,  UR(0),    0   },
/* 15 */   { SO(17),      0,      0,       0,       0,      0,      0,      0,      0,      0,      0,      0,  UE(7),  PE(7),  UE(7),    0   },
/* 16 */   { SO(17),      0,      0,       0,       0, SO(16), SO(16),      0,      0,      0,      0,      0,  UE(8),  PE(8),  UE(8),    0   },
/* 17 */   {     0,       0,      0,       0,       0, SO(18), SO(18),      0,      0,      0,      0,      0,      0,      0,  UR(0),    0   },
/* 18 */   {     0,       0,      0, SF3(19), SF3(19), SO(18), SO(18),      0,      0,      0,      0,      0,  UE(9),  PE(9),  UE(9),    0   },
/* 19 */   {     0,       0,      0,       0,       0,      0, SO(21), SO(20),      0,      0,      0,      0,      0,      0,  UR(0),    0   },
/* 20 */   {     0,       0,      0,       0,       0,      0, SO(21),      0,      0,      0,      0,      0,      0,      0,  UR(0),    0   },
/* 21 */   {     0,       0,      0,       0,       0, SO(21), SO(21),      0,      0,      0,      0,      0, UE(10), PE(10), UE(10),    0   },
/* 22 */   { SO(22), SO(22), SO(22),  SO(22),  SO(22), SO(22), SO(22), SO(22), SO(22), PO(24), PO(23), SO(22), SO(22), SO(22),  UR(0), SO(22) },
/* 23 */   { SO(22), SO(22), SO(22),  SO(22),  SO(22), SO(22), SO(22), SO(22), SO(22), SO(22), SO(22), SO(22), SO(22), SO(22),  UR(0), SO(22) },
/* 24 */   {     0,       0,      0,       0,       0,      0,      0,      0,      0,      0,      0,      0, UE(11), PE(11), UE(11),    0   } };


/* 
 * 局部使用，作为 next_token 的输出参数。
 *
 */
typedef  struct
{
    tetra  type;   /* 使用 LEX_I_XXX 表示分析得出的初步类型.. */
    tetra  info;   /* 配合 type 的进一步的细节信息，如错误子类型. */
    tetra  eat;    /* 在处理中吃掉的字符总数量，用于实现位置信息.. */

    /* 提出出来的需要进一步分析的字符数量，len 就是下面 str 中的实际长度。 */
    tetra  len;    
    tetra  str[LEX_TOKEN_MAX_LEN];
}  token_t;


static  tetra  char_to_class( tetra ch )
{
    if( IS_DOT(ch) )
    {   /* . */
        return  LEX_CH_DOT;
    }
    else if( IS_DOLLAR(ch))
    {   /* $ */
        return  LEX_CH_DOLLAR;
    }
    else if( IS_UDLINE(ch))
    {   /* _ */
        return  LEX_CH_UNDLINE;
    }
    else if( IS_UPPER(ch))
    {   /*  A-Z */
        return  LEX_CH_UPRCASE;
    }
    else if( IS_LOWER(ch))
    {   /*  a-z */
        return  LEX_CH_LOWCASE;
    }
    else if( IS_ZERO(ch) )
    {
        return  LEX_CH_ZERO;
    }
    else if( IS_DIGITAL(ch))
    {   /*  A-Z */
        return  LEX_CH_NOZERO;
    }
    else if( IS_SIGN(ch) )
    {
        return  LEX_CH_SIGN;
    }
    else if( IS_ALPHA(ch) )
    {
        return  LEX_CH_ALPHA;
    }
    else if( IS_DQUOTA(ch))
    {
        return  LEX_CH_QUOTA;
    }
    else if( IS_BSLASH(ch))
    {
        return  LEX_CH_BSLASH;
    }
    else if( IS_COLON(ch) )
    {
        return  LEX_CH_COLON;
    }
    else if( IS_COMMA(ch) )
    {
        return  LEX_CH_COMMA;
    }
    else if( IS_SPACE(ch))
    {
        return  LEX_CH_SPACE;
    }
    else if( IS_LINEND(ch) )
    {
        return  LEX_CH_LINED;
    }
    else if( IS_FILEND(ch) )
    {
        return  LEX_CH_FILED;
    }
    else
    {
        return  LEX_CH_OTHER;
    }
    
}



static  char *  error_str_tbl[] = {
/* 0 */   "good..",
/* 1 */   "too long token string..",
/* 2 */   "program error, not action1..",
/* 3 */   "token not allow....",
/* 4 */   "need a char x or X..",
/* 5 */   "need a char a-f, or A_F..",
/* 6 */   "need a char e or E..",
/* 7 */   "program error, not action2..",
/* 8 */   "program error, not action3..",
/* 9 */   "need a persudo command..",
/* 10 */  "must between 0 ~ 255..",
/* 11 */  "not a number string..",
/* 12 */  "must be @, @+1, @-2..",
/* 13 */  "program error, not + or -..", 
/* 14 */  "must be a string 0x??..",
/* 15 */  "not fit in 64 bits octa..",
/* 16 */  "program error, return a not case.." };



static  tetra  next_token( tetra pin, token_t * ptk )
{
    tetra  ch;
    tetra  cla;
    tetra  state;
    tetra  action;
    tetra  temp;
    
    if( pin == 0 || ptk == NULL )
    {
        return 1;
    }

    /* 初始化..表示未决中间状态 .. */
    ptk->type = LEX_I_NOTEND;
    ptk->info = 0;
    ptk->eat = 0;
    ptk->len = 0;


    for( state=0;; )
    {
        /* 读取出来一个字符, 然后分析他的类别.. */
        ch = in_next_char( pin );
        cla = char_to_class( ch );

        /* 
         * 因为 in 模块保证: 在文件结束符之前, 必然送一个 lined 过来.
         * 而且在状态机数据结构中，实际上也没有针对 filed 的列..
         * 所以这里可以这样写.
         */
        if( cla == LEX_CH_FILED )
        {
            /* utf32 编码，我临时使用 0xFFFFFFF 作为文件结束..*/
            ptk->type = LEX_I_FILED;
            ptk->eat = 1;
            ptk->len = 1;
            ptk->str[0] = 0xFFFFFFFF;
            break;
        }

        /*  
         * 看看上面的 state_machine 定义，认识三个字段的意义。
         */
        if( state >= MAX_STATE )
        {
            /* 这里其实是程序错误，不应该如此.. */
            ptk->type = LEX_I_ERROR;
            ptk->info = ERR_INF_STATE1;
            break;
        }
        
        action = state_machine[state][cla];



#ifdef  _LEX_DBG_
        printf("state : %d, cla : %d, action: 0x%X\n", state, cla, action );
#endif

        /* 
         * 第一个阶段, 对字符是否 存储 进行处理. 
         */
        temp = (action >> 16) & 0xFF;

        if( _STORE_ == temp )
        {
            /* 记录下来，已经处理了一个字符.. */
            ptk->eat += 1;

            /* decide the len , not beyond the 80 */
            if( ptk->len >= LEX_TOKEN_MAX_LEN )
            {
                /* 输出错误信息, 返回 ERROR token. */
                ptk->type = LEX_I_ERROR;
                ptk->info = 2;
                break;
            }

            ptk->str[ptk->len] = ch;
            ptk->len += 1;

        }
        else if( _PASS_ == temp )
        {
            /* 记录下来，已经处理了一个字符.. */
            ptk->eat += 1;

            /* nothing to do .*/
        }
        else if( _UNPUT_ == temp )
        {
            in_unput_char( pin );
        }
        else
        {
            /* 记录下来，已经处理了一个字符.. */
            ptk->eat += 1;

            ptk->type = LEX_I_ERROR;
            ptk->info = ERR_INF_STATE2;
            ptk->str[ptk->len] = ch;
            ptk->len +=1;
            break;
        }


        
        /* 
         * 第二阶段, 决定是否进入下一个状态. 
         * 在这部分处理，我们集中在最后处理 break..
         *
         * ERR : END : OK : FUNC  
         */
         
        temp = action >> 24;
        
        if( temp == _ERR_ )
        {
            ptk->type = LEX_I_ERROR;
            ptk->info = (action & 0xFFFF);
        }
        else if( temp == _END_ )
        {
            /* 终结了，action 剩下部分表示类型. */
            ptk->type = (action & 0xFFFF);
        }
        else if( temp == _OK_ )
        {
            /* 其实表示 continue ，继续，action 剩下部分表示下个状态..*/
            state = (action & 0xFFFF);
        }
        else if( temp == _FUN1_ )
        {
            /* 判断是否是 xX , 用于 16 进制数字串中. */
            if( (ch == 0x58) || (ch==0x78) )
            {
                state = (action & 0xFFFF);
            }
            else
            {
                ptk->type = LEX_I_ERROR;
                ptk->info = ERR_INF_FUN1;
            }
        }
        else if( temp == _FUN2_ )
        {
            /* 判断是否是 a-f 或者 A-F, 用于 16 进制字符串 */
            if( ((ch>=0x41) && (ch<=0x46)) || ((ch>=0x61) && (ch<=0x66)) )
            {
                state = (action & 0xFFFF);
            }
            else
            {
                ptk->type = LEX_I_ERROR;
                ptk->info = ERR_INF_FUN2;;
            }
        }
        else if( temp == _FUN3_ )
        {
            /* 判断是否是 eE, 用于浮点数表示指数部分信息. */
            if( (ch == 0x65) || (ch==0x45) )
            {
                state = (action & 0xFFFF);
            }
            else
            {
                ptk->type = LEX_I_ERROR;
                ptk->info = ERR_INF_FUN3;
            }
        }
        else
        {
            ptk->type = LEX_I_ERROR;
            ptk->info = ERR_INF_STATE3;
        }

        /**/
        if( ptk->type > LEX_I_ERROR )
        {
            ptk->type = LEX_I_ERROR;
            ptk->info = ERR_INF_STATE4;
            break;
        }
        else if( ptk->type != LEX_I_NOTEND )
        {
            /* 已经找到一个 终结 token . */
            break;
        }
        
    }

    /**/
    ptk->str[ptk->len]=0;
    return 0;
    
}







/* 字符串转换. */

/*   没有太多检查, 依赖于调用者保证, 在 len 长度中都是
 *   0-9 字符. 
 *   所以实现简单, 就是遍历, 依次乘 10 .
 *   额外的判断就是 数值是否超过 octa 的表达范围.
 */
static  tetra  ostr_to_octa( tetra * str,  tetra len,  octa * data )
{
    octa  temp1, temp2;
    tetra  i;
    
    if( len == 0 )
    {
        /* 长度为 0 , 非 0 表示失败. */
        return 1;
    }

    temp1 = 0;
    for( i=0; i<len; i++ )
    {
        temp2 = temp1 * 10 + (str[i]-0x30);

        if( temp2 < temp1 )
        {
            /* 发生溢出, 表示超过了 octa 的表达范围. */
            return 2;
        }

        temp1 = temp2;
    }

    *data = temp1;
    return 0;
    
}


static  tetra  hstr_to_octa( tetra * str,  tetra len,  octa * data )
{
    octa  temp1, temp2;
    tetra  i;
    
    if( len == 0 )
    {
        /* 长度为 0 , 非 0 表示失败. */
        return 1;
    }

    temp1 = 0;
    for( i=0; i<len; i++ )
    {
        if( str[i] <= 0x39 )
        {
            temp2 = str[i] - 0x30;
        }
        else if( str[i] <= 0x46 )
        {
            /* a-f : 0x41-0x0A = 0x37 */
            temp2 = str[i]  - 0x37;
        }
        else
        {
            /* a-f : 0x61-0x0A = 0x57 */
            temp2 = str[i]  - 0x57;
        }
        
        temp2 = (temp1 << 4) + temp2;

        if( temp2 < temp1 )
        {
            /* 发生溢出, 表示超过了 octa 的表达范围. */
            return 2;
        }

        temp1 = temp2;
    }

    *data = temp1;
    return 0;
    

}


tetra  ostr_to_double( tetra * str,  tetra len,  double * data )
{
    byte  tempstr[128];
    tetra  i;
    
    if( len > 127 )
    {
        return 1;
    }

    for( i=0; i<len; i++ )
    {
        tempstr[i] = str[i];
    }
    tempstr[len] = 0;

    *data = atof( tempstr );
   
    return 0;
}





// 词法分析的上下文。
typedef  struct
{
    // 输入字符的上下文。
    tetra  ptetra;
    
    // 当前信息, 行号, 位置.

    
} le_context;




tetra  le_init_context( tetra  pin )
{
    le_context * plct;
    
    
    plct = malloc( sizeof(le_context) );                   // malloc();
    if( plct == NULL )
    {
        in_fini_context( pin );
        return 0;
    }

    // 赋初值。
    plct->ptetra = pin;


    // 返回。
    return (tetra)plct;
}


void  le_fini_context( tetra plex )
{
    le_context * plct;

    plct = (le_context *)plex;
    
    in_fini_context( plct->ptetra );
    free( plct );
}


void  le_next_token( tetra plex, lex_token_t * ptoken )
{
    le_context * plct;
    token_t  tkn;

    tetra  tempt;
    octa  tempo;
    double  tempd;
    
    

    /* 调用底层的 状态机 , 取得一个 半成品的 token .. */
    plct = (le_context *)plex;

    tempt = next_token( plct->ptetra, &tkn );
    assert( tempt == 0 );

    /* 其他信息复制 */
    memcpy( ptoken->str, tkn.str, (tkn.len+1)*4 );
    ptoken->len = tkn.len;
    ptoken->eat = tkn.eat;

    
    /* 更细节的信息, 进一步处理，转译.. */
    switch( tkn.type )
    {
    case LEX_I_COMMAND:
        /* 需验证是否是 规定的 伪命令. next_token 已经过滤掉了 '\.'  */
        tempt = find_pseudo( tkn.str, tkn.len );
        if( tempt == 0xFFFFFFFF )
        {
            /* not find... */
            ptoken->type = LEX_TK_ERROR;
            ptoken->info = ERR_INF_PUDO;
        }
        else
        {
            ptoken->type = LEX_TK_COMMAND;
            ptoken->info = tempt;
        }
        break;
        
    case LEX_I_GREG:
        /* 计算是否超过 255 , ?? */
        if( ptoken->len > 3 )
        {
            ptoken->type = LEX_TK_ERROR;
            ptoken->info = ERR_INF_GREG1;
        }
        else
        {
            tempt = ostr_to_octa( tkn.str, tkn.len, &tempo );
            if( tempt != 0 )
            {
                ptoken->type = LEX_TK_ERROR;
                ptoken->info = ERR_INF_GREG2;
            }
            else if( tempo > 255 )
            {
                ptoken->type = LEX_TK_ERROR;
                ptoken->info = ERR_INF_GREG3;
            }
            else
            {
                ptoken->type = LEX_TK_GREG;
                ptoken->info = (tetra) tempo;
            }
        }
        break;
        
    case LEX_I_ALPHA:
        /* 计算偏移, + 0 -  */

        if( ptoken->len == 0 )
        {
            /* 只有  @  一个字符....*/
            ptoken->type = LEX_TK_ALPHA;
            ptoken->info = 0;
            ptoken->valint = 0;
        }
        else if( ptoken->len == 1 )
        {
            /* 不应该出现这种情况出现, @? , 正确的如: @, @+1, @-2. */
            ptoken->type = LEX_TK_ERROR;
            ptoken->info = ERR_INF_ALPH1;
        }
        else
        {
            tempt = ostr_to_octa( &(tkn.str[1]), tkn.len-1, &tempo );
            if( tempt != 0 )
            {
                ptoken->type = LEX_TK_ERROR;
                ptoken->info = ERR_INF_ALPH2;
            }
            else
            {
                if( ptoken->str[0] == 0x2B )
                {
                    /* + 正的偏移. */
                    ptoken->type = LEX_TK_ALPHA;
                    ptoken->info = 0;
                    ptoken->valint = tempo;
                }
                else if( ptoken->str[0] == 0x2D )
                {
                    /* - 负的偏移. */
                    ptoken->type = LEX_TK_ALPHA;
                    ptoken->info = 1;
                    ptoken->valint = tempo;
                }
                else
                {
                    ptoken->type = LEX_TK_ERROR;
                    ptoken->info = ERR_INF_ALPH3;
                }
            }
        }
       
        break;
        
        
    case LEX_I_LABLE:

        /* 计算是否是常量, 是否是指令, 特殊寄存器 : 最后才是 标号.. */
   
        tempt = find_instruction( tkn.str, tkn.len );
        if( tempt != 0xffffffff )
        {
            ptoken->type = LEX_TK_INSTRUCT;
            ptoken->info = tempt;
            break;
        }

        tempt = find_sreg( tkn.str, tkn.len );
        if( tempt != 0xffffffff )
        {
            ptoken->type = LEX_TK_SREG;
            ptoken->info = tempt;
            break;
        }

        tempt = find_const( tkn.str, tkn.len );
        if( tempt != 0xffffffff )
        {
            ptoken->type = LEX_TK_CONST;
            ptoken->info = tempt;
            break;
        }

        ptoken->type = LEX_TK_LABLE;
        ptoken->info = 0;
        break;
        
    case LEX_I_ZERO:
        /* 整数, 0 . */
        ptoken->type = LEX_TK_INTEGER;
        ptoken->info = 0;
        ptoken->valint = 0;
        break;
        
    case LEX_I_HEX:
        /*  0x 或 0X 起始的 16 进制整数. */
        if( ptoken->len <= 2 )
        {
            ptoken->type = LEX_TK_ERROR;
            ptoken->info = ERR_INF_HEX1;
        }
        else
        {
            tetra  tempt;
            octa  tempo;
            tempt = hstr_to_octa( &(tkn.str[2]), tkn.len-2, &tempo );
            if( tempt != 0 )
            {
                ptoken->type = LEX_TK_ERROR;
                ptoken->info = ERR_INF_HEX2;
            }
            else
            {
                ptoken->type = LEX_TK_INTEGER;
                ptoken->info = 0;
                ptoken->valint = tempo;
            }
        }
        
        break;
        
    case LEX_I_SZERO:
        /* 带有 + - 号的 整数 0 . */
        if( ptoken->len < 2 )
        {
            ptoken->type = LEX_TK_ERROR;
            ptoken->info = ERR_INF_SZER1;
        }
        else if( ptoken->str[0] == 0x2B )
        {
            /* + , 允许..*/
            ptoken->type = LEX_TK_INTEGER;
            ptoken->info = 0;
            ptoken->valint = 0;
        }
        else if( ptoken->str[1] == 0x2D )
        {
            /* - , 允许, 但不能出现在 op x,y,z 中, 许要语法中检查...*/
            ptoken->type = LEX_TK_INTEGER;
            ptoken->info = 1;
            ptoken->valint = 0;
        }
        else
        {
            ptoken->type = LEX_TK_ERROR;
            ptoken->info = ERR_INF_SZER2;
        }
        
        break;

        
    case LEX_I_SINT:
        /* 带有 + - 号的非 0 整数.. */
        /* 也可能是没有 + - 号的。 */
        if( ptoken->len == 0  )
        {
            ptoken->type = LEX_TK_ERROR;
            ptoken->info = ERR_INF_SINT1;
        }
        else 
        {
            tetra  tempt;
            octa  tempo;

            if( ptoken->str[0] == 0x2B )
            {
                /* + , 允许..*/
                tempt = ostr_to_octa( &(tkn.str[1]), tkn.len-1, &tempo );
                if( tempt != 0 )
                {
                    ptoken->type = LEX_TK_ERROR;
                    ptoken->info = ERR_INF_SINT2;
                }
                else
                {
                    ptoken->type = LEX_TK_INTEGER;
                    ptoken->info = 0;
                    ptoken->valint = tempo;
                }
            }
            else if( ptoken->str[0] == 0x2D )
            {
                /* - , 允许, 但不能出现在 op x,y,z 中, 许要语法中检查...*/
                tempt = ostr_to_octa( &(tkn.str[1]), tkn.len-1, &tempo );
                if( tempt != 0 )
                {
                    ptoken->type = LEX_TK_ERROR;
                    ptoken->info = ERR_INF_SINT3;
                }
                else
                {
                    ptoken->type = LEX_TK_INTEGER;
                    ptoken->info = 1;
                    ptoken->valint = 0;

                    if( tempo <= 0x8000000000000000ull )
                    {
                        ptoken->valint = tempo;
                    }
                    else
                    {
                        /* 超过范围, 负数不能用 64 位补码表示. */
                        ptoken->type = LEX_TK_ERROR;
                        ptoken->info = ERR_INF_SINT4;
                    }
                }
            }
            else
            {
                tempt = ostr_to_octa( &(tkn.str[0]), tkn.len, &tempo );

                if( tempt != 0 )
                {
                    ptoken->type = LEX_TK_ERROR;
                    ptoken->info = ERR_INF_SINT5;
                }
                else
                {
                    ptoken->type = LEX_TK_INTEGER;
                    ptoken->info = 0;
                    ptoken->valint = tempo;
                }
            }
        }
        
        break;

        
    case LEX_I_FLOAT:

        tempt = ostr_to_double( tkn.str, tkn.len, &tempd );

        if( tempt != 0 )
        {
            ptoken->type = LEX_TK_ERROR;
            ptoken->info = ERR_INF_FLOAT;
        }
        else
        {
            ptoken->type = LEX_TK_FLOAT;
            ptoken->info = 0;
            ptoken->valflt = tempd;
        }
        break;
    
    case LEX_I_FLOATEe:
        {
            tetra  tempi;
            double  tempd;
            tempi = ostr_to_double( tkn.str, tkn.len, &tempd );

            if( tempi != 0 )
            {
                ptoken->type = LEX_TK_ERROR;
                ptoken->info = ERR_INF_FLTE;
            }
            else
            {
                ptoken->type = LEX_TK_FLOAT;
                ptoken->info = 0;
                ptoken->valflt = tempd;
            }
        }
        break;
    
    case LEX_I_STRING:
        ptoken->type = LEX_TK_STRING;
        ptoken->info = 0;
        break;
        
    case LEX_I_COLON:
        ptoken->type = LEX_TK_COLON;
        ptoken->info = 0;
        break;
        
    case LEX_I_COMMA:
        ptoken->type = LEX_TK_COMMA;
        ptoken->info = 0;
        break;
        
    case LEX_I_LINED:
        ptoken->type = LEX_TK_LINED;
        ptoken->info = 0;
        break;
        
    case LEX_I_FILED:
        ptoken->type = LEX_TK_FILED;
        ptoken->info = 0;
        break;
        
    case LEX_I_ERROR: 
        ptoken->type = LEX_TK_ERROR;
        ptoken->info = tkn.info;
        break;
        
    default:
        ptoken->type = LEX_TK_ERROR;
        ptoken->info = ERR_INF_DEFLT;
        break;
        
    }


#ifdef  _LEX_DBG_
    print_tstr( ptoken->str );
    printf("\n");
#endif
    
    return;
    
}





#ifdef  TEST_LEX

int  main()
{
    tetra  pin, plex;
    lex_token_t  token;
    tetra  i,j,k;

    pin = in_init_context( NULL, 0 );
    if( pin == 0 )
    {
        printf("err: in_init_context.");
        return 0;
    }

    plex = le_init_context( pin );
    if( plex == 0 )
    {
        printf("err: le_init_context.");
        return 0;
    }
    
    while(1)
    {
        memset( &token, 0, sizeof(lex_token_t) );
        le_next_token( plex, &token );
        
        
        printf( "\ntype = %d, info = %d ", token.type, token.info );
        printf( "\neat = %d, len = %d\n", token.eat, token.len );
        token.str[token.len] = 0;
        print_tstr( token.str );
        printf( "\nvalint : 0x%08X%08X,", (tetra)(token.valint>>32), (tetra)(token.valint) );
        printf( "\nvalflt : %g", token.valflt );
        printf("\n---------------------------------------------");
        
        if( token.type == LEX_TK_FILED )
        {
            break;
        }
    }

    return 0;
}


#endif

























